/*
 * userapp.c
 *
 * User Application for Alpha-Data ADM-XRC-5T2 accelerator.
 *
 * App  : FPGA Template
 * User : Brittle Tsoi
 * Date : 2009 July
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <admxrc2.h>
#include "userapp.h"
#include "fpga_util.h"

#include <time.h>
#include <sys/time.h>

volatile uint32_t* fpgaReg;
volatile uint8_t*  fpgaMem;

int main(int argc, char *argv[])
{
  int                i;
  uint32_t           buf[0x80000];
  uint32_t           regval;

  struct timeval tv1, tv2, tv3, tv4;
  long long tv_write, tv_read;

  // initial hardware
  if (fpga_init()) {
    fpga_cleanup();
    return -1;
  }

  // initial data
  for (i=0; i<0x80000; i++)
    buf[i] = i;

  // set memory bank and page for Host memory access
  fpga_setbank(0);
  fpga_setpage(0);

  // write data to 5T2 memory
  gettimeofday(&tv1, NULL);
  if (fpga_dmawrite(buf, WINDOW_SIZE)) {
    fpga_cleanup();
    return -1;
  }
  gettimeofday(&tv2, NULL);

  // clear Host data
  memset(buf, 0, 0x200000);
  // clear Device data
  fpga_setbank(1);
  if (fpga_dmawrite(buf, WINDOW_SIZE)) {
    fpga_cleanup();
    return -1;
  }

  // kick start FPGA
  regval = fpgaReg[0x40];
  printf("USER_REG (before) = %08X\n", regval);
  fpgaReg[0x40] = 1;
  sleep_ms(1);

  // wait for FPGA complete
  regval = 0;
  while ((regval&0xFFFFF000) != 0x20000000) {
    regval = fpgaReg[0x40];
  }
  printf("USER_REG (after) = %08X\n", regval);

  // read from 5T2 memory
  gettimeofday(&tv3, NULL);
  if (fpga_dmaread(buf, WINDOW_SIZE)) {
    fpga_cleanup();
    return -1;
  }
  gettimeofday(&tv4, NULL);

  // check results
  for (i=0; i<0x80000; i++)
    if (buf[i] != i)
      printf("expect %08X (%u), but get %08X (%u)\n", i, i, buf[i], buf[i]);

  // link test
  printf("LINK_DAT = [%08X %08X]\n", fpgaReg[0x41], fpgaReg[0x42]);
  if (!(fpgaReg[0x41] & 0x010))
    printf("No connection.\n");
  else {
    printf("Sent %d words, received %d words, ", 
        (fpgaReg[0x41]>>16)+1, (fpgaReg[0x42]>>16)+1);
    if (fpgaReg[0x41] & 1)
      printf("Error detected!\n");
    else
      printf("All correct!\n");
  }

  // cleanup
  fpga_finalize();
  fpga_cleanup();

  tv_write = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
  tv_read = (tv4.tv_sec - tv3.tv_sec) * 1000000 + (tv4.tv_usec - tv3.tv_usec);
  printf("write time = %lld usec (%lldMbps)\n", tv_write, 0x200000*8/tv_write);
  printf("read time = %lld usec (%lldMbps)\n", tv_read, 0x200000*8/tv_read);
	
  return 0;
}

